home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / EXPRESS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-29  |  51.2 KB  |  2,463 lines

  1. /****************************************************************************
  2. *                express.c
  3. *
  4. *  This module implements an expression parser for the floats, vectors and
  5. *  colours in scene description files.
  6. *
  7. *  from Persistence of Vision(tm) Ray Tracer
  8. *  Copyright 1996 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. *  NOTICE: This source code file is provided so that users may experiment
  11. *  with enhancements to POV-Ray and to port the software to platforms other
  12. *  than those supported by the POV-Ray Team.  There are strict rules under
  13. *  which you are permitted to use this file.  The rules are in the file
  14. *  named POVLEGAL.DOC which should be distributed with this file. If
  15. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  17. *  Forum.  The latest version of POV-Ray may be found there as well.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24.  
  25. #include <ctype.h>
  26. #include "frame.h"
  27. #include "vector.h"
  28. #include "povproto.h"
  29. #include "parse.h"
  30. #include "parstxtr.h"
  31. #include "colour.h"
  32. #include "express.h"
  33. #include "matrices.h"
  34. #include "povray.h"
  35. #include "tokenize.h"
  36. #include "pattern.h"
  37. #include "pigment.h"
  38. #include "normal.h"
  39. #include "texture.h"
  40.  
  41.  
  42. /*****************************************************************************
  43. * Local preprocessor defines
  44. ******************************************************************************/
  45.  
  46. #define ftrue(f) ((int)(fabs(f)>EPSILON))
  47.  
  48.  
  49.  
  50. /*****************************************************************************
  51. * Local typedefs
  52. ******************************************************************************/
  53.  
  54.  
  55.  
  56. /*****************************************************************************
  57. * Local variables
  58. ******************************************************************************/
  59.  
  60. static unsigned int Number_Of_Random_Generators;
  61. static unsigned long *next_rand;
  62.  
  63.  
  64. /*****************************************************************************
  65. * Static functions
  66. ******************************************************************************/
  67.  
  68. static void Parse_Vector_Param PARAMS((VECTOR Vector));
  69. static void Parse_Vector_Param2 PARAMS((VECTOR Vect1, VECTOR Vect2));
  70. static void Parse_Num_Factor PARAMS((EXPRESS Express, int *Terms));
  71. static void Parse_Num_Term PARAMS((EXPRESS Express, int *Terms));
  72. static void Parse_Rel_Factor PARAMS((EXPRESS Express, int *Terms));
  73. static void Parse_Rel_Term PARAMS((EXPRESS Express, int *Terms));
  74. static void Parse_Logical PARAMS((EXPRESS Express, int *Terms));
  75. static void Parse_Express PARAMS((EXPRESS Express, int *Terms));
  76. static void Promote_Express PARAMS((EXPRESS Express,int *Old_Terms,int New_Terms));
  77. static void POV_strupr PARAMS((char *s));
  78. static void POV_strlwr PARAMS((char *s));
  79.  
  80. static DBL stream_rand PARAMS((int stream));
  81. static int stream_seed PARAMS((int seed));
  82.  
  83.  
  84.  
  85. /*****************************************************************************
  86. *
  87. * FUNCTION
  88. *
  89. * INPUT
  90. *
  91. * OUTPUT
  92. *
  93. * RETURNS
  94. *
  95. * AUTHOR
  96. *
  97. * DESCRIPTION
  98. *
  99. * CHANGES
  100. *
  101. ******************************************************************************/
  102.  
  103. DBL Parse_Float_Param()
  104. {
  105.   DBL Local;
  106.   EXPRESS Express;
  107.   int Terms = 1;
  108.  
  109.   GET(LEFT_PAREN_TOKEN);
  110.   Parse_Express(Express,&Terms);
  111.  
  112.   if (Terms>1)
  113.   {
  114.     Error ("Float expected but vector or color expression found.");
  115.   }
  116.  
  117.   Local = Express[0];
  118.  
  119.   GET(RIGHT_PAREN_TOKEN);
  120.  
  121.   return (Local);
  122. }
  123.  
  124.  
  125.  
  126. /*****************************************************************************
  127. *
  128. * FUNCTION
  129. *
  130. * INPUT
  131. *
  132. * OUTPUT
  133. *
  134. * RETURNS
  135. *
  136. * AUTHOR
  137. *
  138. * DESCRIPTION
  139. *
  140. * CHANGES
  141. *
  142. ******************************************************************************/
  143.  
  144. void Parse_Float_Param2(Val1,Val2)
  145.   DBL *Val1;
  146.   DBL *Val2;
  147.   {
  148.    GET (LEFT_PAREN_TOKEN);
  149.    *Val1 = Parse_Float();
  150.    Parse_Comma();
  151.    *Val2 = Parse_Float();
  152.    GET (RIGHT_PAREN_TOKEN);
  153.   }
  154.  
  155.  
  156.  
  157. /*****************************************************************************
  158. *
  159. * FUNCTION
  160. *
  161. * INPUT
  162. *
  163. * OUTPUT
  164. *
  165. * RETURNS
  166. *
  167. * AUTHOR
  168. *
  169. * DESCRIPTION
  170. *
  171. * CHANGES
  172. *
  173. ******************************************************************************/
  174.  
  175. static void Parse_Vector_Param(Vector)
  176.   VECTOR Vector;
  177.   {
  178.   GET(LEFT_PAREN_TOKEN);
  179.   Parse_Vector(Vector);
  180.   GET(RIGHT_PAREN_TOKEN);
  181.   }
  182.  
  183.  
  184.  
  185. /*****************************************************************************
  186. *
  187. * FUNCTION
  188. *
  189. * INPUT
  190. *
  191. * OUTPUT
  192. *
  193. * RETURNS
  194. *
  195. * AUTHOR
  196. *
  197. * DESCRIPTION
  198. *
  199. * CHANGES
  200. *
  201. ******************************************************************************/
  202.  
  203. static void Parse_Vector_Param2(Val1,Val2)
  204.   VECTOR Val1;
  205.   VECTOR Val2;
  206.   {
  207.    GET (LEFT_PAREN_TOKEN);
  208.    Parse_Vector(Val1);
  209.    Parse_Comma();
  210.    Parse_Vector(Val2);
  211.    GET (RIGHT_PAREN_TOKEN);
  212.   }
  213.  
  214.  
  215.  
  216. /*****************************************************************************
  217. *
  218. * FUNCTION
  219. *
  220. * INPUT
  221. *
  222. * OUTPUT
  223. *
  224. * RETURNS
  225. *
  226. * AUTHOR
  227. *
  228. * DESCRIPTION
  229. *
  230. * CHANGES
  231. *
  232. ******************************************************************************/
  233.  
  234. static void Parse_Num_Factor (Express,Terms)
  235. EXPRESS Express;
  236. int *Terms;
  237. {
  238.   int i = 0;
  239.   DBL Val,Val2;
  240.   VECTOR Vect,Vect2,Vect3;
  241.   TRANSFORM Trans;
  242.   char *Local_String, *Local_String2;
  243.   FILE *f;
  244.  
  245.   EXPECT
  246.     CASE (FLOAT_FUNCT_TOKEN)
  247.        /* All of these functions return a DBL result */
  248.        switch(Token.Function_Id)
  249.          {
  250.           case ABS_TOKEN:
  251.             Val = Parse_Float_Param();
  252.             Val = fabs(Val);
  253.             break;
  254.  
  255.           case ACOS_TOKEN:
  256.             Val = acos(Parse_Float_Param());
  257.             break;
  258.  
  259.           case VAL_TOKEN:
  260.             GET (LEFT_PAREN_TOKEN);
  261.             Local_String=Parse_String();
  262.             Val = atof(Local_String);
  263.             POV_FREE(Local_String);
  264.             GET (RIGHT_PAREN_TOKEN);
  265.             break;
  266.  
  267.           case ASC_TOKEN:
  268.             GET (LEFT_PAREN_TOKEN);
  269.             Local_String=Parse_String();
  270.             Val = (DBL)Local_String[0];
  271.             POV_FREE(Local_String);
  272.             GET (RIGHT_PAREN_TOKEN);
  273.             break;
  274.  
  275.           case ASIN_TOKEN:
  276.             Val = asin(Parse_Float_Param());
  277.             break;
  278.  
  279.           case ATAN2_TOKEN:
  280.             Parse_Float_Param2(&Val,&Val2);
  281.             Val=atan2(Val,Val2);
  282.             break;
  283.  
  284.           case CEIL_TOKEN:
  285.             Val = ceil(Parse_Float_Param());
  286.             break;
  287.  
  288.           case CLOCK_TOKEN:
  289.             Val = opts.FrameSeq.Clock_Value;
  290.             break;
  291.  
  292.           case COS_TOKEN:
  293.             Val = cos(Parse_Float_Param());
  294.             break;
  295.  
  296.           case DEGREES_TOKEN:
  297.             Val = Parse_Float_Param()/M_PI*180.0;
  298.             break;
  299.  
  300.           case DIV_TOKEN:
  301.             Parse_Float_Param2(&Val,&Val2);
  302.             Val=(DBL) ( (int)(Val/Val2) );
  303.             break;
  304.  
  305.           case EXP_TOKEN:
  306.             Val = exp(Parse_Float_Param());
  307.             break;
  308.  
  309.           case FILE_EXISTS_TOKEN:
  310.             GET (LEFT_PAREN_TOKEN);
  311.             Local_String=Parse_String();
  312.             Val = ((f=Locate_File(Local_String,READ_FILE_STRING,"","",FALSE))==NULL) ? 0.0 : 1.0;
  313.             fclose(f);
  314.             POV_FREE(Local_String);
  315.             GET (RIGHT_PAREN_TOKEN);
  316.             break;
  317.  
  318.           case FLOAT_ID_TOKEN:
  319.             Val = *((DBL *) Token.Constant_Data);
  320.             break;
  321.  
  322.           case FLOAT_TOKEN:
  323.             Val = Token.Token_Float;
  324.             break;
  325.  
  326.           case FLOOR_TOKEN:
  327.             Val = floor(Parse_Float_Param());
  328.             break;
  329.  
  330.           case INT_TOKEN:
  331.             Val = (DBL) ((int) Parse_Float_Param());
  332.             break;
  333.  
  334.           case LOG_TOKEN:
  335.             Val = Parse_Float_Param();
  336.             if (Val<=0.0)
  337.             {
  338.               Error("Log of negative number %lf\n",Val);
  339.             }
  340.             else
  341.             {
  342.               Val = log(Val);
  343.             }
  344.             break;
  345.  
  346.           case MAX_TOKEN:
  347.             Parse_Float_Param2(&Val,&Val2);
  348.             Val = max(Val,Val2);
  349.             break;
  350.  
  351.           case MIN_TOKEN:
  352.             Parse_Float_Param2(&Val,&Val2);
  353.             Val = min(Val,Val2);
  354.             break;
  355.  
  356.           case MOD_TOKEN:
  357.             Parse_Float_Param2(&Val,&Val2);
  358.             Val = fmod(Val,Val2);
  359.             break;
  360.  
  361.           case PI_TOKEN:
  362.             Val = M_PI;
  363.             break;
  364.  
  365.           case POW_TOKEN:
  366.             Parse_Float_Param2(&Val,&Val2);
  367.             Val=pow(Val,Val2);
  368.             break;
  369.  
  370.           case RADIANS_TOKEN:
  371.             Val = Parse_Float_Param()*M_PI/180.0;
  372.             break;
  373.  
  374.           case SIN_TOKEN:
  375.             Val = sin(Parse_Float_Param());
  376.             break;
  377.  
  378.           case SQRT_TOKEN:
  379.             Val = Parse_Float_Param();
  380.             if (Val<0.0)
  381.             {
  382.               Error("sqrt of negative number %lf\n",Val);
  383.             }
  384.             else
  385.             {
  386.               Val = sqrt(Val);
  387.             }
  388.             break;
  389.  
  390.           case STRCMP_TOKEN:
  391.             GET (LEFT_PAREN_TOKEN);
  392.             Local_String=Parse_String();
  393.             Parse_Comma();
  394.             Local_String2=Parse_String();
  395.             Val = (DBL)strcmp(Local_String,Local_String2);
  396.             POV_FREE(Local_String);
  397.             POV_FREE(Local_String2);
  398.             GET (RIGHT_PAREN_TOKEN);
  399.             break;
  400.  
  401.           case STRLEN_TOKEN:
  402.             GET (LEFT_PAREN_TOKEN);
  403.             Local_String=Parse_String();
  404.             Val = (DBL)strlen(Local_String);
  405.             POV_FREE(Local_String);
  406.             GET (RIGHT_PAREN_TOKEN);
  407.             break;
  408.  
  409.           case TAN_TOKEN:
  410.             Val = tan(Parse_Float_Param());
  411.             break;
  412.  
  413.           case VDOT_TOKEN:
  414.             Parse_Vector_Param2(Vect,Vect2);
  415.             VDot(Val,Vect,Vect2);
  416.             break;
  417.  
  418.           case VLENGTH_TOKEN:
  419.             Parse_Vector_Param(Vect);
  420.             VLength(Val,Vect);
  421.             break;
  422.  
  423.           case VERSION_TOKEN:
  424.             Val = opts.Language_Version;
  425.             break;
  426.  
  427.           case TRUE_TOKEN:
  428.           case YES_TOKEN:
  429.           case ON_TOKEN:
  430.             Val = 1.0;
  431.             break;
  432.  
  433.           case FALSE_TOKEN:
  434.           case NO_TOKEN:
  435.           case OFF_TOKEN:
  436.             Val = 0.0;
  437.             break;
  438.  
  439.           case SEED_TOKEN:
  440.             Val = stream_seed((int)Parse_Float_Param());
  441.             break;
  442.  
  443.           case RAND_TOKEN:
  444.             i = (int)Parse_Float_Param();
  445.             if ((i < 0) || (i >= Number_Of_Random_Generators))
  446.             {
  447.               Error("Illegal random number generator.");
  448.             }
  449.             Val = stream_rand(i);
  450.             break;
  451.  
  452.          }
  453.        for (i=0; i < *Terms; i++)
  454.          Express[i]=Val;
  455.        EXIT
  456.      END_CASE
  457.  
  458.      CASE (VECTOR_FUNCT_TOKEN)
  459.        /* All of these functions return a VECTOR result */
  460.        switch(Token.Function_Id)
  461.          {
  462.           case VAXIS_ROTATE_TOKEN:
  463.             GET (LEFT_PAREN_TOKEN);
  464.             Parse_Vector(Vect2);
  465.             Parse_Comma();
  466.             Parse_Vector(Vect3);
  467.             Parse_Comma();
  468.             Val=Parse_Float()*M_PI/180.0;
  469.             GET (RIGHT_PAREN_TOKEN);
  470.             Compute_Axis_Rotation_Transform(&Trans,Vect3,Val);
  471.             MTransPoint(Vect, Vect2, &Trans);
  472.             break;
  473.  
  474.           case VCROSS_TOKEN:
  475.             Parse_Vector_Param2(Vect2,Vect3);
  476.             VCross(Vect,Vect2,Vect3);
  477.             break;
  478.  
  479.           case VECTOR_ID_TOKEN:
  480.             Assign_Vector(Vect,Token.Constant_Data);
  481.             break;
  482.  
  483.           case VNORMALIZE_TOKEN:
  484.             Parse_Vector_Param(Vect2);
  485.             VNormalize(Vect,Vect2);
  486.             break;
  487.  
  488.           case VROTATE_TOKEN:
  489.             Parse_Vector_Param2(Vect2,Vect3);
  490.             Compute_Rotation_Transform (&Trans, Vect3);
  491.             MTransPoint(Vect, Vect2, &Trans);
  492.             break;
  493.  
  494.           case X_TOKEN:
  495.             Make_Vector(Vect,1.0,0.0,0.0)
  496.             break;
  497.  
  498.           case Y_TOKEN:
  499.             Make_Vector(Vect,0.0,1.0,0.0)
  500.             break;
  501.  
  502.           case Z_TOKEN:
  503.             Make_Vector(Vect,0.0,0.0,1.0)
  504.             break;
  505.          }
  506.  
  507.        /* If it was expecting a DBL, promote it to a VECTOR.
  508.           I haven't yet figured out what to do if it was expecting
  509.           a COLOUR value with Terms>3
  510.        */
  511.        if (*Terms==1)
  512.          *Terms=3;
  513.  
  514.        for (i=0; i < 3; i++)
  515.          Express[i]=Vect[i];
  516.        EXIT
  517.      END_CASE
  518.  
  519.      CASE (COLOUR_ID_TOKEN)
  520.        *Terms=5;
  521.        for (i=0; i<5; i++)
  522.          Express[i]=(DBL)(  ((COLC *)(Token.Constant_Data))[i]  );
  523.        EXIT
  524.      END_CASE
  525.  
  526.      CASE (T_TOKEN)
  527.        *Terms=4;
  528.        Express[0]=0.0;
  529.        Express[1]=0.0;
  530.        Express[2]=0.0;
  531.        Express[3]=1.0;
  532.        EXIT
  533.      END_CASE
  534.  
  535.      CASE (U_TOKEN)
  536.        *Terms=2;
  537.        Express[0]=1.0;
  538.        Express[1]=0.0;
  539.        EXIT
  540.      END_CASE
  541.  
  542.      CASE (V_TOKEN)
  543.        *Terms=2;
  544.        Express[0]=0.0;
  545.        Express[1]=1.0;
  546.        EXIT
  547.      END_CASE
  548.  
  549.      CASE (PLUS_TOKEN)
  550.      END_CASE
  551.  
  552.      CASE (DASH_TOKEN)
  553.        Parse_Num_Factor(Express,Terms);
  554.        for (i=0; i<*Terms; i++)
  555.          Express[i]=-Express[i];
  556.        EXIT
  557.      END_CASE
  558.  
  559.      CASE (EXCLAMATION_TOKEN)
  560.        Parse_Num_Factor(Express,Terms);
  561.        for (i=0; i<*Terms; i++)
  562.          Express[i] = ftrue(Express[i])?0.0:1.0;
  563.        EXIT
  564.      END_CASE
  565.  
  566.      CASE (LEFT_PAREN_TOKEN)
  567.        Parse_Express(Express,Terms);
  568.        GET(RIGHT_PAREN_TOKEN);
  569.        EXIT
  570.      END_CASE
  571.  
  572. /* This case parses a 2, 3, 4, or 5 term vector.  First parse 2 terms.
  573.    Note Parse_Comma won't crash if it doesn't find one.
  574.  */
  575.  
  576.      CASE (LEFT_ANGLE_TOKEN)
  577.        Express[X] = Parse_Float();   Parse_Comma();
  578.        Express[Y] = Parse_Float();   Parse_Comma();
  579.  
  580.        EXPECT
  581.          CASE_EXPRESS
  582.            /* If a 3th float is found, parse it. */
  583.            Express[2] = Parse_Float(); Parse_Comma();
  584.            *Terms=3;
  585.            EXPECT
  586.              CASE_EXPRESS
  587.                /* If a 4th float is found, parse it. */
  588.                Express[3] = Parse_Float(); Parse_Comma();
  589.                *Terms=4;
  590.                EXPECT
  591.                  CASE_EXPRESS
  592.                    /* If a 5th float is found, parse it. */
  593.                    Express[4] = Parse_Float();
  594.                    *Terms=5;
  595.                  END_CASE
  596.  
  597.                  OTHERWISE
  598.                    /* Only 4 found. */
  599.                    UNGET
  600.                    GET (RIGHT_ANGLE_TOKEN)
  601.                    EXIT
  602.                  END_CASE
  603.                END_EXPECT
  604.                EXIT
  605.              END_CASE
  606.  
  607.              OTHERWISE
  608.                /* Only 3 found. */
  609.                UNGET
  610.                GET (RIGHT_ANGLE_TOKEN)
  611.                EXIT
  612.              END_CASE
  613.            END_EXPECT
  614.            EXIT
  615.          END_CASE
  616.  
  617.          OTHERWISE
  618.            /* Only 2 found. */
  619.            UNGET
  620.            GET (RIGHT_ANGLE_TOKEN)
  621.            EXIT
  622.          END_CASE
  623.        END_EXPECT
  624.        EXIT
  625.      END_CASE
  626.  
  627.      OTHERWISE
  628.        Parse_Error_Str ("numeric expression");
  629.      END_CASE
  630.    END_EXPECT
  631.  
  632.    /* Parse VECTOR.x or COLOR.red type things */
  633.    EXPECT
  634.      CASE(PERIOD_TOKEN)
  635.        EXPECT
  636.          CASE (VECTOR_FUNCT_TOKEN)
  637.            switch(Token.Function_Id)
  638.            {
  639.              case X_TOKEN:
  640.                i=X;
  641.                break;
  642.  
  643.              case Y_TOKEN:
  644.                i=Y;
  645.                break;
  646.  
  647.              case Z_TOKEN:
  648.                i=Z;
  649.                break;
  650.                
  651.              default:
  652.                Parse_Error_Str ("x, y, or z");
  653.            }
  654.            EXIT
  655.          END_CASE
  656.  
  657.          CASE (COLOUR_KEY_TOKEN)
  658.            switch(Token.Function_Id)
  659.            {
  660.              case RED_TOKEN:
  661.                i=RED;
  662.                break;
  663.                
  664.              case GREEN_TOKEN:
  665.                i=GREEN;
  666.                break;
  667.  
  668.              case BLUE_TOKEN:
  669.                i=BLUE;
  670.                break;
  671.  
  672.              case FILTER_TOKEN:
  673.                i=FILTER;
  674.                break;
  675.                
  676.              case TRANSMIT_TOKEN:
  677.                i=TRANSM;
  678.                break;
  679.                
  680.              default:
  681.                Parse_Error_Str ("red, green, blue, filter, or transmit");
  682.            }
  683.            EXIT
  684.          END_CASE
  685.  
  686.          CASE(U_TOKEN)
  687.            i=U;
  688.            EXIT
  689.          END_CASE
  690.  
  691.          CASE(V_TOKEN)
  692.            i=V;
  693.            EXIT
  694.          END_CASE
  695.  
  696.          CASE(T_TOKEN)
  697.            i=T;
  698.            EXIT
  699.          END_CASE
  700.  
  701.          OTHERWISE
  702.            Parse_Error_Str ("x, y, z or color component");
  703.          END_CASE
  704.        END_EXPECT
  705.  
  706.        if (i>=*Terms)
  707.        {
  708.           Error("Bad operands for period operator.");
  709.        }
  710.        *Terms=1;
  711.        Express[0]=Express[i];
  712.        EXIT
  713.      END_CASE
  714.      
  715.      OTHERWISE
  716.        UNGET
  717.        EXIT
  718.      END_CASE
  719.    END_EXPECT
  720.   }
  721.  
  722.  
  723.  
  724. /*****************************************************************************
  725. *
  726. * FUNCTION
  727. *
  728. * INPUT
  729. *
  730. * OUTPUT
  731. *
  732. * RETURNS
  733. *
  734. * AUTHOR
  735. *
  736. * DESCRIPTION
  737. *
  738. * CHANGES
  739. *
  740. ******************************************************************************/
  741.  
  742. /* If first operand of a 2-operand function had more terms than the second,
  743.    then the parsing of the 2nd operand would have automatically promoted it.
  744.    But if 2nd operand has more terms then we must go back promote the 1st
  745.    operand before combining them  Promote_Express does it.  If Old_Terms=1
  746.    then set all terms to Express[0].  Otherwise pad extra terms with 0.0.
  747. */
  748.  
  749. static void Promote_Express(Express,Old_Terms,New_Terms)
  750.   EXPRESS Express;
  751.   int *Old_Terms;
  752.   int New_Terms;
  753.   {
  754.    register int i;
  755.  
  756.    if (*Old_Terms >= New_Terms)
  757.      return;
  758.  
  759.    if (*Old_Terms==1)
  760.    {
  761.      for(i=1;i<New_Terms;i++)
  762.      {
  763.         Express[i]=Express[0];
  764.      }
  765.    }
  766.    else
  767.    {
  768.      for(i=(*Old_Terms);i<New_Terms;i++)
  769.      {
  770.         Express[i]=0.0;
  771.      }
  772.    }
  773.  
  774.    *Old_Terms=New_Terms;
  775.   }
  776.  
  777.  
  778.  
  779.  
  780. /*****************************************************************************
  781. *
  782. * FUNCTION
  783. *
  784. * INPUT
  785. *
  786. * OUTPUT
  787. *
  788. * RETURNS
  789. *
  790. * AUTHOR
  791. *
  792. * DESCRIPTION
  793. *
  794. * CHANGES
  795. *
  796. ******************************************************************************/
  797.  
  798. static void Parse_Num_Term (Express,Terms)
  799.   EXPRESS Express;
  800.   int *Terms;
  801.   {
  802.    register int i;
  803.    EXPRESS Local_Express;
  804.    int Local_Terms;
  805.  
  806.    Parse_Num_Factor(Express,Terms);
  807.  
  808.    Local_Terms=*Terms;
  809.  
  810.    EXPECT
  811.      CASE (STAR_TOKEN)
  812.        Parse_Num_Factor(Local_Express,&Local_Terms);
  813.        Promote_Express(Express,Terms,Local_Terms);
  814.  
  815.        for(i=0;i<*Terms;i++)
  816.          Express[i] *= Local_Express[i];
  817.      END_CASE
  818.  
  819.      CASE (SLASH_TOKEN)
  820.        Parse_Num_Factor(Local_Express,&Local_Terms);
  821.        Promote_Express(Express,Terms,Local_Terms);
  822.  
  823.        for(i=0;i<*Terms;i++)
  824.          Express[i] /= Local_Express[i];
  825.      END_CASE
  826.  
  827.      OTHERWISE
  828.        UNGET
  829.        EXIT
  830.      END_CASE
  831.    END_EXPECT
  832.  
  833.   }
  834.  
  835.  
  836.  
  837. /*****************************************************************************
  838. *
  839. * FUNCTION
  840. *
  841. * INPUT
  842. *
  843. * OUTPUT
  844. *
  845. * RETURNS
  846. *
  847. * AUTHOR
  848. *
  849. * DESCRIPTION
  850. *
  851. * CHANGES
  852. *
  853. ******************************************************************************/
  854.  
  855. static void Parse_Rel_Factor (Express,Terms)
  856.   EXPRESS Express;
  857.   int *Terms;
  858.   {
  859.    register int i;
  860.    EXPRESS Local_Express;
  861.    int Local_Terms;
  862.  
  863.    Parse_Num_Term(Express,Terms);
  864.  
  865.    Local_Terms=*Terms;
  866.  
  867.    EXPECT
  868.      CASE (PLUS_TOKEN)
  869.        Parse_Num_Term(Local_Express,&Local_Terms);
  870.        Promote_Express(Express,Terms,Local_Terms);
  871.  
  872.        for(i=0;i<*Terms;i++)
  873.          Express[i] += Local_Express[i];
  874.      END_CASE
  875.  
  876.      CASE (DASH_TOKEN)
  877.        Parse_Num_Term(Local_Express,&Local_Terms);
  878.        Promote_Express(Express,Terms,Local_Terms);
  879.  
  880.        for(i=0;i<*Terms;i++)
  881.          Express[i] -= Local_Express[i];
  882.      END_CASE
  883.  
  884.      OTHERWISE
  885.        UNGET
  886.        EXIT
  887.      END_CASE
  888.    END_EXPECT
  889.  
  890.   }
  891.  
  892.  
  893.  
  894. /*****************************************************************************
  895. *
  896. * FUNCTION
  897. *
  898. * INPUT
  899. *
  900. * OUTPUT
  901. *
  902. * RETURNS
  903. *
  904. * AUTHOR
  905. *
  906. * DESCRIPTION
  907. *
  908. * CHANGES
  909. *
  910. ******************************************************************************/
  911.  
  912. static void Parse_Rel_Term (Express,Terms)
  913.   EXPRESS Express;
  914.   int *Terms;
  915.   {
  916.    register int i;
  917.    EXPRESS Local_Express;
  918.    int Local_Terms;
  919.  
  920.    Parse_Rel_Factor(Express,Terms);
  921.  
  922.    Local_Terms=*Terms;
  923.  
  924.    EXPECT
  925.      CASE (LEFT_ANGLE_TOKEN)
  926.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  927.        Promote_Express(Express,Terms,Local_Terms);
  928.  
  929.        for(i=0;i<*Terms;i++)
  930.          Express[i] = (DBL)(Express[i] < Local_Express[i]);
  931.      END_CASE
  932.  
  933.      CASE (REL_LE_TOKEN)
  934.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  935.        Promote_Express(Express,Terms,Local_Terms);
  936.  
  937.        for(i=0;i<*Terms;i++)
  938.          Express[i] = (DBL)(Express[i] <= Local_Express[i]);
  939.      END_CASE
  940.  
  941.      CASE (EQUALS_TOKEN)
  942.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  943.        Promote_Express(Express,Terms,Local_Terms);
  944.  
  945.        for(i=0;i<*Terms;i++)
  946.          Express[i] = (DBL)(!ftrue(Express[i]-Local_Express[i]));
  947.      END_CASE
  948.  
  949.      CASE (REL_NE_TOKEN)
  950.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  951.        Promote_Express(Express,Terms,Local_Terms);
  952.  
  953.        for(i=0;i<*Terms;i++)
  954.          Express[i] = (DBL)ftrue(Express[i]-Local_Express[i]);
  955.      END_CASE
  956.  
  957.      CASE (REL_GE_TOKEN)
  958.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  959.        Promote_Express(Express,Terms,Local_Terms);
  960.  
  961.        for(i=0;i<*Terms;i++)
  962.          Express[i] = (DBL)(Express[i] >= Local_Express[i]);
  963.      END_CASE
  964.  
  965.      CASE (RIGHT_ANGLE_TOKEN)
  966.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  967.        Promote_Express(Express,Terms,Local_Terms);
  968.  
  969.        for(i=0;i<*Terms;i++)
  970.          Express[i] = (DBL)(Express[i] > Local_Express[i]);
  971.      END_CASE
  972.  
  973.      OTHERWISE
  974.        UNGET
  975.        EXIT
  976.      END_CASE
  977.    END_EXPECT
  978.  
  979.   }
  980.  
  981.  
  982.  
  983. /*****************************************************************************
  984. *
  985. * FUNCTION
  986. *
  987. * INPUT
  988. *
  989. * OUTPUT
  990. *
  991. * RETURNS
  992. *
  993. * AUTHOR
  994. *
  995. * DESCRIPTION
  996. *
  997. * CHANGES
  998. *
  999. ******************************************************************************/
  1000.  
  1001. static void Parse_Logical (Express,Terms)
  1002.   EXPRESS Express;
  1003.   int *Terms;
  1004.   {
  1005.    register int i;
  1006.    EXPRESS Local_Express;
  1007.    int Local_Terms;
  1008.  
  1009.    Parse_Rel_Term(Express,Terms);
  1010.  
  1011.    Local_Terms=*Terms;
  1012.  
  1013.    EXPECT
  1014.      CASE (AMPERSAND_TOKEN)
  1015.        Parse_Rel_Term(Local_Express,&Local_Terms);
  1016.        Promote_Express(Express,Terms,Local_Terms);
  1017.  
  1018.        for(i=0;i<*Terms;i++)
  1019.          Express[i] = (DBL)(ftrue(Express[i]) && ftrue(Local_Express[i]));
  1020.      END_CASE
  1021.  
  1022.      CASE (BAR_TOKEN)
  1023.        Parse_Rel_Term(Local_Express,&Local_Terms);
  1024.        Promote_Express(Express,Terms,Local_Terms);
  1025.  
  1026.        for(i=0;i<*Terms;i++)
  1027.          Express[i] = (DBL)(ftrue(Express[i]) || ftrue(Local_Express[i]));
  1028.      END_CASE
  1029.  
  1030.      OTHERWISE
  1031.        UNGET
  1032.        EXIT
  1033.      END_CASE
  1034.    END_EXPECT
  1035.  
  1036.   }
  1037.  
  1038.  
  1039.  
  1040. /*****************************************************************************
  1041. *
  1042. * FUNCTION
  1043. *
  1044. * INPUT
  1045. *
  1046. * OUTPUT
  1047. *
  1048. * RETURNS
  1049. *
  1050. * AUTHOR
  1051. *
  1052. * DESCRIPTION
  1053. *
  1054. * CHANGES
  1055. *
  1056. ******************************************************************************/
  1057.  
  1058. static void Parse_Express (Express,Terms)
  1059.   EXPRESS Express;
  1060.   int *Terms;
  1061.   {
  1062.    EXPRESS Local_Express1, Local_Express2;
  1063.    EXPRESS *Chosen;
  1064.    int Local_Terms1, Local_Terms2;
  1065.  
  1066.    Local_Terms1 = 1;
  1067.  
  1068.    Parse_Logical(Express,&Local_Terms1);
  1069.  
  1070.    EXPECT
  1071.      CASE (QUESTION_TOKEN)
  1072.        if (Local_Terms1 != 1)
  1073.          Error("Conditional must evaluate to a float.");
  1074.        Local_Terms1 = Local_Terms2 = *Terms;
  1075.        Parse_Express(Local_Express1,&Local_Terms1);
  1076.        GET(COLON_TOKEN);
  1077.        Parse_Express(Local_Express2,&Local_Terms2);
  1078.        if (ftrue(Express[0]))
  1079.          {
  1080.           Chosen = (EXPRESS *)&Local_Express1;
  1081.           *Terms = Local_Terms1;
  1082.          }
  1083.        else
  1084.          {
  1085.           Chosen = (EXPRESS *)&Local_Express2;
  1086.           *Terms = Local_Terms2;
  1087.          }
  1088.        memcpy(Express,Chosen,sizeof(EXPRESS));
  1089.        EXIT
  1090.      END_CASE
  1091.  
  1092.      OTHERWISE
  1093.        /* Not a (c)?a:b expression.  Since Express was parsed with
  1094.           Local_Terms1=1 then we may have to promote this.  Suppose
  1095.           Terms=3 but Local_Terms1=1.  If this had been a (c)?a:b
  1096.           then a float is ok but since it is not a condition then
  1097.           it must be promoted to Terms=3.  Note that the parameters
  1098.           below look wrong but they are not.
  1099.         */
  1100.        Promote_Express (Express,&Local_Terms1,*Terms);
  1101.        /* On the other hand, Local_Terms1 may be bigger than Terms.
  1102.           If so, Express already is promoted and Terms must reflect that.
  1103.         */
  1104.        *Terms=Local_Terms1;
  1105.        UNGET
  1106.        EXIT
  1107.      END_CASE
  1108.    END_EXPECT
  1109.  
  1110.   }
  1111.  
  1112.  
  1113.  
  1114. /*****************************************************************************
  1115. *
  1116. * FUNCTION
  1117. *
  1118. * INPUT
  1119. *
  1120. * OUTPUT
  1121. *
  1122. * RETURNS
  1123. *
  1124. * AUTHOR
  1125. *
  1126. * DESCRIPTION
  1127. *
  1128. * CHANGES
  1129. *
  1130. ******************************************************************************/
  1131.  
  1132. DBL Parse_Raw_Number()
  1133. {
  1134.   int Terms;
  1135.   DBL Val;
  1136.   EXPRESS Express;
  1137.  
  1138.   Terms = 1;
  1139.  
  1140.   Parse_Num_Factor(Express, &Terms);
  1141.  
  1142.   Val = Express[0];
  1143.  
  1144.   if (Terms != 1)
  1145.   {
  1146.     Error("Raw float expected but vector found instead.");
  1147.   }
  1148.  
  1149.   return (Val);
  1150. }
  1151.  
  1152.  
  1153.  
  1154. /*****************************************************************************
  1155. *
  1156. * FUNCTION
  1157. *
  1158. * INPUT
  1159. *
  1160. * OUTPUT
  1161. *
  1162. * RETURNS
  1163. *
  1164. * AUTHOR
  1165. *
  1166. * DESCRIPTION
  1167. *
  1168. * CHANGES
  1169. *
  1170. ******************************************************************************/
  1171.  
  1172. DBL Parse_Float ()
  1173.   {
  1174.    EXPRESS Express;
  1175.    int Terms;
  1176.  
  1177.    Terms=1;
  1178.  
  1179.    if (opts.Language_Version < 1.5)
  1180.           Parse_Num_Factor(Express,&Terms);
  1181.    else
  1182.       Parse_Rel_Factor(Express,&Terms);
  1183.  
  1184.    if (Terms>1)
  1185.       Error ("Float expected but vector or color expression found.");
  1186.  
  1187.    return (Express[0]);
  1188.   }
  1189.  
  1190.  
  1191.  
  1192. /*****************************************************************************
  1193. *
  1194. * FUNCTION
  1195. *
  1196. * INPUT
  1197. *
  1198. * OUTPUT
  1199. *
  1200. * RETURNS
  1201. *
  1202. * AUTHOR
  1203. *
  1204. * DESCRIPTION
  1205. *
  1206. * CHANGES
  1207. *
  1208. ******************************************************************************/
  1209.  
  1210. DBL Allow_Float (defval)
  1211.   DBL defval;
  1212.   {
  1213.   DBL retval;
  1214.  
  1215.   EXPECT
  1216.     CASE_EXPRESS
  1217.       retval = Parse_Float();
  1218.       EXIT
  1219.     END_CASE
  1220.  
  1221.     OTHERWISE
  1222.       UNGET
  1223.       retval = defval;
  1224.       EXIT
  1225.     END_CASE
  1226.   END_EXPECT
  1227.  
  1228.   return (retval);
  1229.   }
  1230.  
  1231.  
  1232.  
  1233. /*****************************************************************************
  1234. *
  1235. * FUNCTION
  1236. *
  1237. * INPUT
  1238. *
  1239. * OUTPUT
  1240. *
  1241. * RETURNS
  1242. *
  1243. * AUTHOR
  1244. *
  1245. * DESCRIPTION
  1246. *
  1247. * CHANGES
  1248. *
  1249. ******************************************************************************/
  1250.  
  1251. void Parse_Vector (Vector)
  1252.   VECTOR Vector;
  1253.   {
  1254.    EXPRESS Express;
  1255.    int Terms;
  1256.  
  1257.    /* Initialize expression. [DB 12/94] */
  1258.  
  1259.    for (Terms = 0; Terms < 5; Terms++)
  1260.    {
  1261.      Express[Terms] = 0.0;
  1262.    }
  1263.  
  1264.    Terms=3;
  1265.  
  1266.    if (opts.Language_Version < 1.5)
  1267.           Parse_Num_Factor(Express,&Terms);
  1268.    else
  1269.       Parse_Rel_Factor(Express,&Terms);
  1270.  
  1271.    if (Terms>3)
  1272.       Error ("Vector expected but color expression found.");
  1273.  
  1274.    for(Terms=0;Terms<3;Terms++)
  1275.       Vector[Terms]=Express[Terms];
  1276.   }
  1277.  
  1278.  
  1279. /*****************************************************************************
  1280. *
  1281. * FUNCTION
  1282. *
  1283. * INPUT
  1284. *
  1285. * OUTPUT
  1286. *
  1287. * RETURNS
  1288. *
  1289. * AUTHOR
  1290. *
  1291. * DESCRIPTION
  1292. *
  1293. * CHANGES
  1294. *
  1295. ******************************************************************************/
  1296.  
  1297. void Parse_Vector4D (Vector)
  1298.   VECTOR Vector;
  1299.   {
  1300.    EXPRESS Express;
  1301.    int Terms;
  1302.    int Dim = 4;
  1303.    /* Initialize expression. [DB 12/94] */
  1304.  
  1305.    for (Terms = 0; Terms < 5; Terms++)
  1306.    {
  1307.      Express[Terms] = 0.0;
  1308.    }
  1309.  
  1310.    Terms=Dim;
  1311.  
  1312.    if (opts.Language_Version < 1.5)
  1313.           Parse_Num_Factor(Express,&Terms);
  1314.    else
  1315.       Parse_Rel_Factor(Express,&Terms);
  1316.  
  1317.    if (Terms>Dim)
  1318.       Error ("Vector expected but color expression found.");
  1319.  
  1320.    for(Terms=0;Terms<Dim;Terms++)
  1321.       Vector[Terms]=Express[Terms];
  1322.   }
  1323.  
  1324.  
  1325.  
  1326.  
  1327. /*****************************************************************************
  1328. *
  1329. * FUNCTION
  1330. *
  1331. * INPUT
  1332. *
  1333. * OUTPUT
  1334. *
  1335. * RETURNS
  1336. *
  1337. * AUTHOR
  1338. *
  1339. * DESCRIPTION
  1340. *
  1341. * CHANGES
  1342. *
  1343. ******************************************************************************/
  1344.  
  1345. void Parse_UV_Vect (UV_Vect)
  1346.   UV_VECT UV_Vect;
  1347.   {
  1348.    EXPRESS Express;
  1349.    int Terms;
  1350.  
  1351.    /* Initialize expression. [DB 12/94] */
  1352.  
  1353.    for (Terms = 0; Terms < 5; Terms++)
  1354.    {
  1355.      Express[Terms] = 0.0;
  1356.    }
  1357.  
  1358.    Terms=2;
  1359.  
  1360.    if (opts.Language_Version < 1.5)
  1361.           Parse_Num_Factor(Express,&Terms);
  1362.    else
  1363.       Parse_Rel_Factor(Express,&Terms);
  1364.  
  1365.    if (Terms>2)
  1366.       Error ("UV_Vector expected but vector or color expression found.");
  1367.  
  1368.    for(Terms=0;Terms<2;Terms++)
  1369.       UV_Vect[Terms]=Express[Terms];
  1370.   }
  1371.  
  1372.  
  1373.  
  1374. /*****************************************************************************
  1375. *
  1376. * FUNCTION
  1377. *
  1378. * INPUT
  1379. *
  1380. * OUTPUT
  1381. *
  1382. * RETURNS
  1383. *
  1384. * AUTHOR
  1385. *
  1386. * DESCRIPTION
  1387. *
  1388. * CHANGES
  1389. *
  1390. ******************************************************************************/
  1391.  
  1392. void Parse_Vector_Float(Vector)
  1393.   VECTOR Vector;
  1394.   {
  1395.    EXPRESS Express;
  1396.    int Terms;
  1397.  
  1398.    /* Initialize expression. [DB 12/94] */
  1399.  
  1400.    for (Terms = 0; Terms < 5; Terms++)
  1401.    {
  1402.      Express[Terms] = 0.0;
  1403.    }
  1404.  
  1405.    Terms=1;
  1406.  
  1407.    if (opts.Language_Version < 1.5)
  1408.           Parse_Num_Factor(Express,&Terms);
  1409.    else
  1410.       Parse_Rel_Factor(Express,&Terms);
  1411.  
  1412.    if (Terms>3)
  1413.       Error ("Vector or float expected but color expression found.");
  1414.  
  1415.    Have_Vector=(Terms==3);
  1416.  
  1417.    if (Have_Vector)
  1418.      for(Terms=0;Terms<3;Terms++)
  1419.        Vector[Terms]=Express[Terms];
  1420.    else
  1421.      for(Terms=0;Terms<3;Terms++)
  1422.        Vector[Terms]=Express[0];
  1423.   }
  1424.  
  1425.  
  1426. /*****************************************************************************
  1427. *
  1428. * FUNCTION
  1429. *
  1430. * INPUT
  1431. *
  1432. * OUTPUT
  1433. *
  1434. * RETURNS
  1435. *
  1436. * AUTHOR
  1437. *
  1438. * DESCRIPTION
  1439. *
  1440. * CHANGES
  1441. *
  1442. ******************************************************************************/
  1443.  
  1444. void Parse_Scale_Vector (Vector)
  1445.   VECTOR Vector;
  1446.   {
  1447.    Parse_Vector(Vector);
  1448.  
  1449.    if (Vector[X] == 0.0)
  1450.     {
  1451.      Vector[X] = 1.0;
  1452.      Warn(0.0, "Illegal Value: Scale X by 0.0. Changed to 1.0.");
  1453.     }
  1454.    if (Vector[Y] == 0.0)
  1455.     {
  1456.      Vector[Y] = 1.0;
  1457.      Warn(0.0, "Illegal Value: Scale Y by 0.0. Changed to 1.0.");
  1458.     }
  1459.    if (Vector[Z] == 0.0)
  1460.     {
  1461.      Vector[Z] = 1.0;
  1462.      Warn(0.0, "Illegal Value: Scale Z by 0.0. Changed to 1.0.");
  1463.     }
  1464.   }
  1465.  
  1466.  
  1467.  
  1468. /*****************************************************************************
  1469. *
  1470. * FUNCTION
  1471. *
  1472. * INPUT
  1473. *
  1474. * OUTPUT
  1475. *
  1476. * RETURNS
  1477. *
  1478. * AUTHOR
  1479. *
  1480. * DESCRIPTION
  1481. *
  1482. * CHANGES
  1483. *
  1484. ******************************************************************************/
  1485.  
  1486. void Parse_Colour (Colour)
  1487.   COLOUR Colour;
  1488.   {
  1489.   EXPRESS Express;
  1490.   int Terms;
  1491.   register int i;
  1492.  
  1493.   /* Initialize expression. [DB 12/94] */
  1494.  
  1495.   for (Terms = 0; Terms < 5; Terms++)
  1496.   {
  1497.     Express[Terms] = 0.0;
  1498.   }
  1499.  
  1500.   Make_Colour (Colour, 0.0, 0.0, 0.0);
  1501.  
  1502.   ALLOW(COLOUR_TOKEN)
  1503.  
  1504.   EXPECT
  1505.     CASE (COLOUR_KEY_TOKEN)
  1506.       switch(Token.Function_Id)
  1507.         {
  1508.          case ALPHA_TOKEN:
  1509.            Warn(1.55, "Keyword ALPHA discontinued. Use FILTER instead.");
  1510.            /* missing break deliberate */
  1511.  
  1512.          case FILTER_TOKEN:
  1513.                    Colour[FILTER] = (COLC)Parse_Float();
  1514.                    break;
  1515.  
  1516.          case BLUE_TOKEN:
  1517.                    Colour[BLUE] = (COLC)Parse_Float();
  1518.                    break;
  1519.  
  1520.          case GREEN_TOKEN:
  1521.                    Colour[GREEN] = (COLC)Parse_Float();
  1522.                    break;
  1523.  
  1524.          case RED_TOKEN:
  1525.                    Colour[RED] = (COLC)Parse_Float();
  1526.                    break;
  1527.  
  1528.          case TRANSMIT_TOKEN:
  1529.                    Colour[TRANSM] = (COLC)Parse_Float();
  1530.                    break;
  1531.  
  1532.          case RGB_TOKEN:
  1533.            Terms=3;
  1534.            Parse_Express(Express,&Terms);
  1535.            if (Terms != 3)
  1536.              Warn(0.0, "Suspicious expression after rgb.");
  1537.            for (i=0;i<Terms;i++)
  1538.              Colour[i]=(COLC)Express[i];
  1539.            break;
  1540.  
  1541.          case RGBF_TOKEN:
  1542.            Terms=4;
  1543.            Parse_Express(Express,&Terms);
  1544.            if (Terms != 4)
  1545.              Warn(0.0, "Suspicious expression after rgbf.");
  1546.            for (i=0;i<Terms;i++)
  1547.              Colour[i]=(COLC)Express[i];
  1548.            break;
  1549.  
  1550.          case RGBT_TOKEN:
  1551.            Terms=4;
  1552.            Parse_Express(Express,&Terms);
  1553.            if (Terms != 4)
  1554.              Warn(0.0, "Suspicious expression after rgbt.");
  1555.            for (i=0;i<Terms;i++)
  1556.              Colour[i]=(COLC)Express[i];
  1557.            Colour[TRANSM]=Colour[FILTER];
  1558.            Colour[FILTER]=0.0;
  1559.            break;
  1560.  
  1561.          case RGBFT_TOKEN:
  1562.            Terms=5;
  1563.            Parse_Express(Express,&Terms);
  1564.            if (Terms != 5)
  1565.              Warn(0.0, "Suspicious expression after rgbft.");
  1566.            for (i=0;i<Terms;i++)
  1567.              Colour[i]=(COLC)Express[i];
  1568.            break;
  1569.         }
  1570.     END_CASE
  1571.  
  1572.     CASE (COLOUR_ID_TOKEN)
  1573.       UNGET
  1574.       Terms=5;
  1575.       Parse_Express(Express,&Terms);
  1576.       for (i=0;i<Terms;i++)
  1577.         Colour[i]=(COLC)Express[i];
  1578.     END_CASE
  1579.  
  1580.     CASE_EXPRESS
  1581.       UNGET
  1582.       Terms=5;
  1583.       Parse_Express(Express,&Terms);
  1584.       if (Terms != 5)
  1585.         Error("Color expression expected but float or vector expression found.");
  1586.       for (i=0;i<Terms;i++)
  1587.         Colour[i]=(COLC)Express[i];
  1588.     END_CASE
  1589.  
  1590.     OTHERWISE
  1591.       UNGET
  1592.       EXIT
  1593.     END_CASE
  1594.   END_EXPECT
  1595. }
  1596.  
  1597. /*****************************************************************************
  1598. *
  1599. * FUNCTION
  1600. *
  1601. *   Parse_Blend_Map
  1602. *
  1603. * INPUT
  1604. *
  1605. *   Type of map to parse: pigment_map, normal_map etc
  1606. *   
  1607. * OUTPUT
  1608. *   
  1609. * RETURNS
  1610. *
  1611. *   Pointer to created blend map
  1612. *   
  1613. * AUTHOR
  1614. *
  1615. *   Chris Young 11/94
  1616. *   
  1617. * DESCRIPTION   :
  1618. *
  1619. * CHANGES
  1620. *
  1621. ******************************************************************************/
  1622.  
  1623. BLEND_MAP *Parse_Blend_Map (Blend_Type,Pat_Type)
  1624. int Blend_Type,Pat_Type;
  1625.   {
  1626.    BLEND_MAP *New = NULL;
  1627.    BLEND_MAP_ENTRY *Temp_Ent;
  1628.    int i;
  1629.  
  1630.    Parse_Begin ();
  1631.  
  1632.    EXPECT
  1633.      CASE2 (COLOUR_MAP_ID_TOKEN, PIGMENT_MAP_ID_TOKEN)
  1634.      CASE3 (NORMAL_MAP_ID_TOKEN, TEXTURE_MAP_ID_TOKEN, SLOPE_MAP_ID_TOKEN)
  1635.        New = Copy_Blend_Map ((BLEND_MAP *) Token.Constant_Data);
  1636.        EXIT
  1637.      END_CASE
  1638.  
  1639.      OTHERWISE
  1640.        UNGET
  1641.        Temp_Ent = Create_BMap_Entries(MAX_BLEND_MAP_ENTRIES);
  1642.        i = 0;
  1643.  
  1644.        EXPECT
  1645.          CASE (LEFT_SQUARE_TOKEN)
  1646.            switch (Pat_Type)
  1647.            {
  1648.               case AVERAGE_PATTERN:
  1649.                 Temp_Ent[i].value = Allow_Float(1.0);
  1650.                 Parse_Comma();
  1651.                 break;
  1652.               
  1653.               default:
  1654.                 Temp_Ent[i].value = Parse_Float();
  1655.                 Parse_Comma();
  1656.                 break;
  1657.            }
  1658.  
  1659.            switch (Blend_Type)
  1660.            {
  1661.             case PIGMENT_TYPE:
  1662.               Temp_Ent[i].Vals.Pigment=Copy_Pigment(Default_Texture->Pigment);
  1663.               Parse_Pigment(&(Temp_Ent[i].Vals.Pigment));
  1664.               break;
  1665.  
  1666.             case NORMAL_TYPE:
  1667.               Temp_Ent[i].Vals.Tnormal=Copy_Tnormal(Default_Texture->Tnormal);
  1668.               Parse_Tnormal(&(Temp_Ent[i].Vals.Tnormal));
  1669.               break;
  1670.  
  1671.             case SLOPE_TYPE:
  1672.               Parse_UV_Vect(Temp_Ent[i].Vals.Point_Slope);
  1673.               break;
  1674.  
  1675.             case TEXTURE_TYPE:
  1676.               Temp_Ent[i].Vals.Texture=Parse_Texture();
  1677.               break;
  1678.  
  1679.             default:
  1680.               Error("Type not implemented yet.");
  1681.            }
  1682.            if (++i > MAX_BLEND_MAP_ENTRIES)
  1683.              Error ("Blend_Map too long");
  1684.  
  1685.            GET (RIGHT_SQUARE_TOKEN);
  1686.          END_CASE
  1687.  
  1688.          OTHERWISE
  1689.            UNGET
  1690.            if (i < 1)
  1691.              Error ("Must have at least one entry in map.");
  1692.            New = Create_Blend_Map ();
  1693.            New->Number_Of_Entries = i;
  1694.            New->Type=Blend_Type;
  1695.            New->Transparency_Flag=TRUE; /*Temp fix.  Really set in Post_???*/
  1696.            New->Blend_Map_Entries = POV_REALLOC(Temp_Ent,sizeof(BLEND_MAP_ENTRY)*i,"blend map entries");
  1697.            EXIT
  1698.          END_CASE
  1699.        END_EXPECT
  1700.        EXIT
  1701.      END_CASE
  1702.    END_EXPECT
  1703.  
  1704.    Parse_End ();
  1705.  
  1706.    return (New);
  1707.   }
  1708.  
  1709.  
  1710.  
  1711. /*****************************************************************************
  1712. *
  1713. * FUNCTION
  1714. *
  1715. * INPUT
  1716. *
  1717. * OUTPUT
  1718. *
  1719. * RETURNS
  1720. *
  1721. * AUTHOR
  1722. *
  1723. * DESCRIPTION
  1724. *
  1725. * CHANGES
  1726. *
  1727. ******************************************************************************/
  1728.  
  1729. BLEND_MAP *Parse_Blend_List (Count,Def_Map,Blend_Type)
  1730.   int Count;
  1731.   BLEND_MAP *Def_Map;
  1732.   int Blend_Type;
  1733.   {
  1734.    BLEND_MAP *New;
  1735.    BLEND_MAP_ENTRY *Temp_Ent;
  1736.    int Type, i;
  1737.  
  1738.    i = 0;
  1739.  
  1740.    if(Blend_Type == PIGMENT_TYPE)
  1741.    {
  1742.      EXPECT
  1743.        CASE(PIGMENT_TOKEN)
  1744.          UNGET
  1745.          Type=PIGMENT_TYPE;
  1746.          EXIT
  1747.        END_CASE
  1748.  
  1749.        OTHERWISE
  1750.          UNGET
  1751.          Type=COLOUR_TYPE;
  1752.          EXIT
  1753.        END_CASE
  1754.      END_EXPECT
  1755.    }
  1756.    else
  1757.    {
  1758.      Type=Blend_Type;
  1759.    }
  1760.  
  1761.    Temp_Ent = Create_BMap_Entries(Count);
  1762.  
  1763.    switch(Type)
  1764.    {
  1765.      case COLOUR_TYPE:
  1766.        EXPECT
  1767.          CASE_COLOUR
  1768.          CASE_EXPRESS
  1769.            Parse_Colour (Temp_Ent[i].Vals.Colour);
  1770.            Parse_Comma ();
  1771.            Temp_Ent[i].value = (SNGL)i;
  1772.            if (++i >= Count)
  1773.              EXIT
  1774.          END_CASE
  1775.  
  1776.          OTHERWISE
  1777.            UNGET
  1778.            EXIT
  1779.          END_CASE
  1780.        END_EXPECT
  1781.        break;
  1782.  
  1783.      case PIGMENT_TYPE:
  1784.        EXPECT
  1785.          CASE(PIGMENT_TOKEN)
  1786.            Parse_Begin ();
  1787.            Temp_Ent[i].Vals.Pigment=Copy_Pigment(Default_Texture->Pigment);
  1788.            Parse_Pigment(&(Temp_Ent[i].Vals.Pigment));
  1789.            Parse_End ();
  1790.            Parse_Comma ();
  1791.            Temp_Ent[i].value = (SNGL)i;
  1792.            if (++i >= Count)
  1793.              EXIT
  1794.          END_CASE
  1795.  
  1796.          OTHERWISE
  1797.            UNGET
  1798.            EXIT
  1799.          END_CASE
  1800.        END_EXPECT
  1801.        break;
  1802.  
  1803.      case NORMAL_TYPE:
  1804.        EXPECT
  1805.          CASE(TNORMAL_TOKEN)
  1806.            Parse_Begin ();
  1807.            Temp_Ent[i].Vals.Tnormal=Copy_Tnormal(Default_Texture->Tnormal);
  1808.            Parse_Tnormal(&(Temp_Ent[i].Vals.Tnormal));
  1809.            Parse_End ();
  1810.            Parse_Comma ();
  1811.            Temp_Ent[i].value = (SNGL)i;
  1812.            if (++i >= Count)
  1813.              EXIT
  1814.          END_CASE
  1815.  
  1816.          OTHERWISE
  1817.            UNGET
  1818.            EXIT
  1819.          END_CASE
  1820.        END_EXPECT
  1821.        break;
  1822.  
  1823.      case TEXTURE_TYPE:
  1824.        EXPECT
  1825.          CASE(TEXTURE_TOKEN)
  1826.            Parse_Begin ();
  1827.            Temp_Ent[i].Vals.Texture=Parse_Texture();
  1828.            Parse_End ();
  1829.            Parse_Comma ();
  1830.            Temp_Ent[i].value = (SNGL)i;
  1831.            if (++i >= Count)
  1832.              EXIT
  1833.          END_CASE
  1834.  
  1835.          OTHERWISE
  1836.            UNGET
  1837.            EXIT
  1838.          END_CASE
  1839.        END_EXPECT
  1840.        break;
  1841.  
  1842.    }
  1843.    
  1844.    if ((Type==NORMAL_TYPE) && (i==0))
  1845.    {
  1846.      POV_FREE(Temp_Ent);
  1847.      return (NULL);
  1848.    }
  1849.  
  1850.    while (i < Count)
  1851.    {
  1852.      switch (Type)
  1853.      {
  1854.         case COLOUR_TYPE:
  1855.           Assign_Colour(Temp_Ent[i].Vals.Colour,Def_Map->Blend_Map_Entries[i].Vals.Colour);
  1856.           break;
  1857.  
  1858.         case PIGMENT_TYPE:
  1859.           Temp_Ent[i].Vals.Pigment=Copy_Pigment(Default_Texture->Pigment);
  1860.           break;
  1861.  
  1862.         case NORMAL_TYPE:
  1863.           Temp_Ent[i].Vals.Tnormal=Copy_Tnormal(Default_Texture->Tnormal);
  1864.           break;
  1865.  
  1866.         case TEXTURE_TYPE:
  1867.           Temp_Ent[i].Vals.Texture=Copy_Textures(Default_Texture);
  1868.           break;
  1869.  
  1870.      }
  1871.      Temp_Ent[i].value = (SNGL)i;
  1872.      i++;
  1873.    }
  1874.  
  1875.    New = Create_Blend_Map ();
  1876.    New->Number_Of_Entries = Count;
  1877.    New->Type=Type;
  1878.    New->Transparency_Flag=TRUE; /*Temp fix.  Really set in Post_???*/
  1879.    New->Blend_Map_Entries = Temp_Ent;
  1880.  
  1881.    return (New);
  1882.   }
  1883.  
  1884.  
  1885. /*****************************************************************************
  1886. *
  1887. * FUNCTION
  1888. *
  1889. *   Parse_Colour_Map
  1890. *
  1891. * INPUT
  1892. *   
  1893. * OUTPUT
  1894. *
  1895. * RETURNS
  1896. *
  1897. *   Pointer to newly created BLEND_MAP that has colors as all
  1898. *   its entries.
  1899. *   
  1900. * AUTHOR
  1901. *
  1902. *   POV-Ray Team
  1903. *   
  1904. * DESCRIPTION   : This seperate routine parses color_maps only.  It
  1905. *                 cannot be used for pigment_maps because it accomidates
  1906. *                 the old double entry color maps from vers 1.0
  1907. *
  1908. * CHANGES
  1909. *
  1910. ******************************************************************************/
  1911.  
  1912. BLEND_MAP *Parse_Colour_Map ()
  1913.   {
  1914.    BLEND_MAP *New = NULL;
  1915.    int i,j,c,p,ii;
  1916.    EXPRESS Express;
  1917.    int Terms;
  1918.    BLEND_MAP_ENTRY *Temp_Ent;
  1919.  
  1920.    Parse_Begin ();
  1921.  
  1922.    EXPECT
  1923.      CASE (COLOUR_MAP_ID_TOKEN)
  1924.        New = Copy_Blend_Map ((BLEND_MAP *) Token.Constant_Data);
  1925.        EXIT
  1926.      END_CASE
  1927.  
  1928.      OTHERWISE
  1929.        UNGET
  1930.        Temp_Ent = Create_BMap_Entries(MAX_BLEND_MAP_ENTRIES);
  1931.        i = 0;
  1932.        j = 1;
  1933.  
  1934.        EXPECT
  1935.          CASE (LEFT_SQUARE_TOKEN)
  1936.            Temp_Ent[i].value = Parse_Float();  Parse_Comma();
  1937.  
  1938.            EXPECT
  1939.              /* After [ must be a float. If 2nd thing found is another
  1940.                 float then this is an old style color_map.
  1941.               */
  1942.              CASE_FLOAT
  1943.                Terms=1;
  1944.                Parse_Express(Express,&Terms);
  1945.                if (Terms==1)
  1946.                  {
  1947.                   Temp_Ent[j].value = Express[0];
  1948.                   Parse_Colour (Temp_Ent[i].Vals.Colour);
  1949.  
  1950.                   GET (COLOUR_TOKEN);
  1951.                   Parse_Colour (Temp_Ent[j].Vals.Colour);
  1952.                   i += 2;
  1953.                   j += 2;
  1954.                  }
  1955.                else
  1956.                  if (Terms==5)
  1957.                    {
  1958.                     for (ii=0;ii<5;ii++)
  1959.                       Temp_Ent[i].Vals.Colour[ii]=(COLC)Express[ii];
  1960.                     i++;
  1961.                     j++;
  1962.                    }
  1963.                  else
  1964.                    Error("Illegal expression syntax in color_map.");
  1965.                EXIT
  1966.              END_CASE
  1967.  
  1968.              CASE_COLOUR
  1969.                Parse_Colour (Temp_Ent[i].Vals.Colour);
  1970.                i++;
  1971.                j++;
  1972.                EXIT
  1973.              END_CASE
  1974.  
  1975.            END_EXPECT
  1976.  
  1977.            if (j > MAX_BLEND_MAP_ENTRIES)
  1978.              Error ("Blend_Map too long.");
  1979.  
  1980.            GET (RIGHT_SQUARE_TOKEN);
  1981.          END_CASE
  1982.  
  1983.          OTHERWISE
  1984.            UNGET
  1985.            if (i < 1)
  1986.              Error ("Must have at least one color in color map.");
  1987.  
  1988.            /* Eliminate duplicates */
  1989.            for (c = 1, p = 0; c<i; c++)
  1990.              {
  1991.               if (memcmp(&(Temp_Ent[p]),
  1992.                          &(Temp_Ent[c]),sizeof(BLEND_MAP_ENTRY)) == 0)
  1993.                 p--;
  1994.  
  1995.               Temp_Ent[++p] = Temp_Ent[c];
  1996.              }
  1997.            p++;
  1998.            New = Create_Blend_Map ();
  1999.            New->Number_Of_Entries = p;
  2000.            New->Type=COLOUR_TYPE;
  2001.            New->Transparency_Flag=TRUE; /*Temp fix.  Really set in Post_???*/
  2002.            New->Blend_Map_Entries = POV_REALLOC(Temp_Ent,sizeof(BLEND_MAP_ENTRY)*p,"blend map entries");
  2003.            EXIT
  2004.          END_CASE
  2005.        END_EXPECT
  2006.        EXIT
  2007.      END_CASE
  2008.    END_EXPECT
  2009.  
  2010.    Parse_End ();
  2011.  
  2012.    return (New);
  2013.   }
  2014.  
  2015.  
  2016.  
  2017. /*****************************************************************************
  2018. *
  2019. * FUNCTION
  2020. *
  2021. * INPUT
  2022. *
  2023. * OUTPUT
  2024. *
  2025. * RETURNS
  2026. *
  2027. * AUTHOR
  2028. *
  2029. * DESCRIPTION
  2030. *
  2031. * CHANGES
  2032. *
  2033. ******************************************************************************/
  2034.  
  2035. char *Parse_String()
  2036. {
  2037.   char *temp1, *temp2, *New = NULL, *p;
  2038.   char temp3[64];
  2039.   char temp4[64];
  2040.   DBL val;
  2041.   int l,l2,d;
  2042.  
  2043.   EXPECT
  2044.     CASE(STRING_LITERAL_TOKEN)
  2045.       New=POV_MALLOC(strlen(Token.Token_String) + 1, "temporary string");
  2046.       strcpy (New, Token.Token_String);
  2047.       EXIT
  2048.     END_CASE
  2049.  
  2050.     CASE(STR_TOKEN)
  2051.       GET (LEFT_PAREN_TOKEN);
  2052.       val = Parse_Float();
  2053.       Parse_Comma();
  2054.       l = (int)Parse_Float();
  2055.       Parse_Comma();
  2056.       d = (int)Parse_Float();
  2057.       GET (RIGHT_PAREN_TOKEN);
  2058.  
  2059.       p=temp3;
  2060.       *(p++) = '%';
  2061.       if (l>0)
  2062.       {
  2063.         sprintf(p,"%d",l);
  2064.         while (*(++p));
  2065.         /* Could also be written for clarity as:
  2066.         while (*p != '\0')
  2067.           p++;
  2068.         */
  2069.       }
  2070.       else
  2071.       {
  2072.         if (l)
  2073.         {
  2074.           sprintf(p,"0%d",abs(l));
  2075.           while (*(++p));
  2076.         }
  2077.       }
  2078.       
  2079.       if (d>=0)
  2080.       {
  2081.         *(p++) = '.';
  2082.         sprintf(p,"%d",d);
  2083.         while (*(++p));
  2084.       }
  2085.       *(p++) = 'f';
  2086.       *p     = '\0';
  2087.             
  2088.       sprintf(temp4,temp3,val);
  2089.       
  2090.       New=POV_MALLOC(strlen(temp4) + 1, "temporary string");
  2091.       strcpy (New, temp4);
  2092.       EXIT
  2093.     END_CASE
  2094.  
  2095.     CASE(CONCAT_TOKEN)
  2096.       GET (LEFT_PAREN_TOKEN);
  2097.       
  2098.       New=Parse_String();
  2099.       EXPECT
  2100.         CASE(RIGHT_PAREN_TOKEN)
  2101.           EXIT
  2102.         END_CASE
  2103.         
  2104.         OTHERWISE
  2105.           Parse_Comma();
  2106.           temp1=New;
  2107.           temp2=Parse_String();
  2108.           if ((l2=strlen(temp1)+strlen(temp2)+2) > 400)
  2109.           {
  2110.              Error("String too long.");
  2111.           }
  2112.           New=POV_MALLOC(l2, "temporary string");
  2113.           strcpy(New,temp1);
  2114.           strcat(New,temp2);
  2115.           POV_FREE(temp1);
  2116.           POV_FREE(temp2);
  2117.         END_CASE
  2118.       END_EXPECT       
  2119.       EXIT
  2120.     END_CASE
  2121.     
  2122.     CASE(CHR_TOKEN)
  2123.       New=POV_MALLOC(2, "temporary string");
  2124.       d=(int)Parse_Float_Param();
  2125.       if ((d<0)||(d>255))
  2126.       {
  2127.         Error("Value %d cannot be used in chr(...).\n",d);
  2128.       }
  2129.       New[0]=d;
  2130.       New[1]='\0';
  2131.       EXIT
  2132.     END_CASE
  2133.     
  2134.     CASE(SUBSTR_TOKEN)
  2135.       GET (LEFT_PAREN_TOKEN);
  2136.       
  2137.       temp1=Parse_String();
  2138.       Parse_Comma();
  2139.       l=(int)Parse_Float();
  2140.       Parse_Comma();
  2141.       d=(int)Parse_Float();
  2142.       if ((l+d-1) > strlen(temp1))
  2143.       {
  2144.          Error("Illegal params in substr(%s,%d,%d).\n",temp1,l,d);
  2145.       }
  2146.       New=POV_MALLOC((size_t)(d+1), "temporary string");
  2147.       strncpy(New,&(temp1[l-1]),(unsigned)d);
  2148.       New[d]='\0';
  2149.       POV_FREE(temp1);
  2150.       GET (RIGHT_PAREN_TOKEN);
  2151.       EXIT
  2152.     END_CASE
  2153.     
  2154.     CASE(STRUPR_TOKEN)
  2155.       GET (LEFT_PAREN_TOKEN);
  2156.       New=Parse_String();
  2157.       POV_strupr(New);
  2158.       GET (RIGHT_PAREN_TOKEN);
  2159.       EXIT
  2160.     END_CASE
  2161.     
  2162.     CASE(STRLWR_TOKEN)
  2163.       GET (LEFT_PAREN_TOKEN);
  2164.       New=Parse_String();
  2165.       POV_strlwr(New);
  2166.       GET (RIGHT_PAREN_TOKEN);
  2167.       EXIT
  2168.     END_CASE
  2169.     
  2170.     CASE(STRING_ID_TOKEN)
  2171.       New=POV_MALLOC(strlen(Token.Constant_Data) + 1, "temporary string");
  2172.       strcpy (New, Token.Constant_Data);
  2173.       EXIT
  2174.     END_CASE
  2175.       
  2176.     OTHERWISE
  2177.       Parse_Error_Str ("string expression");
  2178.     END_CASE
  2179.   END_EXPECT
  2180.  
  2181.   return (New);
  2182. }
  2183.  
  2184.  
  2185.  
  2186. /*****************************************************************************
  2187. *
  2188. * FUNCTION
  2189. *
  2190. * INPUT
  2191. *
  2192. * OUTPUT
  2193. *
  2194. * RETURNS
  2195. *
  2196. * AUTHOR
  2197. *
  2198. * DESCRIPTION
  2199. *
  2200. * CHANGES
  2201. *
  2202. ******************************************************************************/
  2203.  
  2204. char *Parse_Formatted_String()
  2205. {
  2206.   char *New, *src, *dest;
  2207.  
  2208.   New = src = dest = Parse_String();
  2209.  
  2210.   while (*src != '\0')
  2211.   {
  2212.     if (*src=='\\')
  2213.     {
  2214.       switch(*(++src))
  2215.       {
  2216.         case 'a': *dest=0x07; break;
  2217.            
  2218.         case 'b': *dest=0x08; break;
  2219.  
  2220.         case 'f': *dest=0x0c; break;
  2221.  
  2222.         case 'n': *dest=0x0a; break;
  2223.  
  2224.         case 'r': *dest=0x0d; break;
  2225.  
  2226.         case 't': *dest=0x09; break;
  2227.  
  2228.         case 'v': *dest=0x0b; break;
  2229.  
  2230.         case '\0': 
  2231.         case '\\': *dest=0x5c; break;
  2232.  
  2233.         case '\'': *dest=0x27; break;
  2234.            
  2235.         default: *dest='\\'; dest++; *dest=*src; break;
  2236.       }
  2237.     }
  2238.     else
  2239.     {
  2240.       *dest=*src;
  2241.     }
  2242.     src++;
  2243.     dest++;
  2244.   }
  2245.   *dest='\0';
  2246.   return (New);
  2247. }
  2248.  
  2249.  
  2250. /*****************************************************************************
  2251. *
  2252. * FUNCTION
  2253. *
  2254. * INPUT
  2255. *
  2256. * OUTPUT
  2257. *
  2258. * RETURNS
  2259. *
  2260. * AUTHOR
  2261. *
  2262. * DESCRIPTION
  2263. *
  2264. * CHANGES
  2265. *
  2266. ******************************************************************************/
  2267.  
  2268. static void POV_strupr(s)
  2269. char *s;
  2270. {
  2271.   int i;
  2272.   
  2273.   for (i = 0; i < strlen(s); i++)
  2274.   {
  2275.     s[i] = (char)toupper((int)s[i]);
  2276.   }
  2277. }
  2278.  
  2279.  
  2280.  
  2281. /*****************************************************************************
  2282. *
  2283. * FUNCTION
  2284. *
  2285. * INPUT
  2286. *
  2287. * OUTPUT
  2288. *
  2289. * RETURNS
  2290. *
  2291. * AUTHOR
  2292. *
  2293. * DESCRIPTION
  2294. *
  2295. * CHANGES
  2296. *
  2297. ******************************************************************************/
  2298.  
  2299. static void POV_strlwr(s)
  2300. char *s;
  2301. {
  2302.   int i;
  2303.   
  2304.   for (i = 0; i < strlen(s); i++)
  2305.   {
  2306.     s[i] = (char)tolower((int)s[i]);
  2307.   }
  2308. }
  2309.  
  2310.  
  2311. /*****************************************************************************
  2312. *
  2313. * FUNCTION
  2314. *
  2315. *   stream_rand
  2316. *
  2317. * INPUT
  2318. *
  2319. *   stream - number of random stream
  2320. *
  2321. * OUTPUT
  2322. *
  2323. * RETURNS
  2324. *
  2325. *   DBL - random value
  2326. *
  2327. * AUTHOR
  2328. *
  2329. *   Dieter Bayer
  2330. *
  2331. * DESCRIPTION
  2332. *
  2333. *   Standard pseudo-random function.
  2334. *
  2335. * CHANGES
  2336. *
  2337. *   Feb 1996 : Creation.
  2338. *   Mar 1996 : Return 2^32 random values instead of 2^16 [AED]
  2339. *
  2340. ******************************************************************************/
  2341.  
  2342. static DBL stream_rand(stream)
  2343. int stream;
  2344. {
  2345.   next_rand[stream] = next_rand[stream] * 1812433253L + 12345L;
  2346.  
  2347.   return((DBL)(next_rand[stream] & 0xFFFFFFFFUL) / 0xFFFFFFFFUL);
  2348. }
  2349.  
  2350.  
  2351.  
  2352. /*****************************************************************************
  2353. *
  2354. * FUNCTION
  2355. *
  2356. *   stream_seed
  2357. *
  2358. * INPUT
  2359. *
  2360. *   seed - Pseudo-random generator start value
  2361. *
  2362. * OUTPUT
  2363. *
  2364. * RETURNS
  2365. *
  2366. * AUTHOR
  2367. *
  2368. *   Dieter Bayer
  2369. *
  2370. * DESCRIPTION
  2371. *
  2372. *   Set start value for pseudo-random generator.
  2373. *
  2374. * CHANGES
  2375. *
  2376. *   Feb 1996 : Creation.
  2377. *
  2378. ******************************************************************************/
  2379.  
  2380. static int stream_seed(seed)
  2381. int seed;
  2382. {
  2383.   next_rand = (unsigned long *)POV_REALLOC(next_rand, (Number_Of_Random_Generators+1)*sizeof(unsigned long), "random number generator");
  2384.  
  2385.   next_rand[Number_Of_Random_Generators] = (unsigned long int)seed;
  2386.  
  2387.   Number_Of_Random_Generators++;
  2388.  
  2389.   return(Number_Of_Random_Generators-1);
  2390. }
  2391.  
  2392.  
  2393.  
  2394. /*****************************************************************************
  2395. *
  2396. * FUNCTION
  2397. *
  2398. *   Init_Random_Generators
  2399. *
  2400. * INPUT
  2401. *
  2402. * OUTPUT
  2403. *
  2404. * RETURNS
  2405. *
  2406. * AUTHOR
  2407. *
  2408. *   Dieter Bayer
  2409. *
  2410. * DESCRIPTION
  2411. *
  2412. * CHANGES
  2413. *
  2414. *   Feb 1996 : Creation.
  2415. *
  2416. ******************************************************************************/
  2417.  
  2418. void Init_Random_Generators()
  2419. {
  2420.   Number_Of_Random_Generators = 0;
  2421.  
  2422.   next_rand = NULL;
  2423. }
  2424.  
  2425.  
  2426.  
  2427. /*****************************************************************************
  2428. *
  2429. * FUNCTION
  2430. *
  2431. *   Destroy_Random_Generators
  2432. *
  2433. * INPUT
  2434. *
  2435. * OUTPUT
  2436. *
  2437. * RETURNS
  2438. *
  2439. * AUTHOR
  2440. *
  2441. *   Dieter Bayer
  2442. *
  2443. * DESCRIPTION
  2444. *
  2445. * CHANGES
  2446. *
  2447. *   Feb 1996 : Creation.
  2448. *
  2449. ******************************************************************************/
  2450.  
  2451. void Destroy_Random_Generators()
  2452. {
  2453.   if (next_rand != NULL)
  2454.   {
  2455.     POV_FREE(next_rand);
  2456.   }
  2457.  
  2458.   next_rand = NULL;
  2459.  
  2460.   Number_Of_Random_Generators = 0;
  2461. }
  2462.  
  2463.